package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.sun.org.apache.bcel.internal.generic.NEW;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import sun.misc.Cleaner;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ProductFeignClient productFeignClient;


    @Override
    public void addToCart(Long skuId, String userId, Integer skuNum) {
   /*
   存储购物车数据：redis hash ：hset key=user:userId:cart field=skuId value=cartInfo实体
    1、先判断购物车中是否存在该商品
        true： update数量相加
               默认选中
               赋值修改时间
        false: insert
    2、添加购车时，购物车有没有这个商品，默认都是选中状态
       添加时要添加 createTime 和 updateTime
    3、存入redis中

        */
        //1.首先组成购物车的key 然后存入redis缓存中
        String cartKey = getCartKey(userId);
        //根据skuId获取数据
        CartInfo cartInfoExist = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
//        CartInfo cartInfoExist1 = (CartInfo) this.redisTemplate.boundHashOps(cartKey).get(skuId.toString());

        //判断购物车数据是否存在
        if (cartInfoExist != null) {//如果购物车有数据
            //防止超卖
          /*  if (cartInfoExist.getSkuNum()>200){
                cartInfoExist.setSkuNum(200);
            }*/
            //数量
            cartInfoExist.setSkuNum(cartInfoExist.getSkuNum() + skuNum);
            //默认选中
            if (cartInfoExist.getIsChecked().intValue() == 0) {
                cartInfoExist.setIsChecked(1);
            }
            //修改为更新后的时间
            cartInfoExist.setUpdateTime(new Date());
            //将数据放入到redis缓存中
            this.redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfoExist);

        } else {//购物车无数据  通过skuId获取skuInfo
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            //方法1：
            CartInfo cartInfo = new CartInfo();
            cartInfo.setSkuId(skuId);//商品唯一标识skuId
            cartInfo.setSkuNum(skuNum);//商品数量
            cartInfo.setUserId(userId);//登录的用户id
//            cartInfo.setSkuPrice(skuInfo.getPrice());//可能走得是redis缓存
            cartInfo.setSkuPrice(this.productFeignClient.getSkuPrice(skuId));
            cartInfo.setCartPrice(this.productFeignClient.getSkuPrice(skuId));//放入购车时的价格
            cartInfo.setSkuName(skuInfo.getSkuName());
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());//默认图片
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());
            //将数据放入到redis缓存中
            this.redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfo);
            cartInfoExist = cartInfo;
//            方法2：
    /*
                cartInfoExist = new CartInfo();
                cartInfoExist.setSkuId(skuId);//商品唯一标识skuId
                cartInfoExist.setSkuNum(skuNum);//商品数量
                cartInfoExist.setUserId(userId);//登录的用户id
                cartInfo.setSkuPrice(skuInfo.getPrice());//可能走得是redis缓存
                cartInfoExist.setSkuPrice(this.productFeignClient.getSkuPrice(skuId));
                cartInfoExist.setCartPrice(this.productFeignClient.getSkuPrice(skuId));//放入购车时的价格
                cartInfoExist.setSkuName(skuInfo.getSkuName());
                cartInfoExist.setImgUrl(skuInfo.getSkuDefaultImg());//默认图片
                cartInfoExist.setCreateTime(new Date());
                cartInfoExist.setUpdateTime(new Date());
                //将数据放入到redis缓存中
                this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);
    */

        }
    }

    @Override
    public List<CartInfo> cartList(String userId, String userTempId) {
        //1、 声明一个未登录集合来存储数据
        List<CartInfo> noLoginCartInfoList = new ArrayList<>();

        //未登录：只有临时用户id 没有userId  查询未登录购物车数据排序并返回
        if (!StringUtils.isEmpty(userTempId)) {
            //从缓存中获取购物车的key
            String cartKey = this.getCartKey(userTempId);
            //hset key field hget key field  hgetAll key [key value]  hvals key [value]
            noLoginCartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        }
        //排序 按照修改的时间排序
        if (StringUtils.isEmpty(userId)) {   //没有登录的userId
            if (!CollectionUtils.isEmpty(noLoginCartInfoList)) {
                noLoginCartInfoList.sort((o1, o2) -> {
                    return o2.getUpdateTime().compareTo(o1.getUpdateTime());
                    //方法2、return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);//两个都可以
                });
            }
            return noLoginCartInfoList;
        }
         /*
            登录：
                case 1: userId userTempId
                case 2: userId
         */

        //2、 声明一个登录购物车集合来存储数据
//        List<CartInfo> loginCartInfoList = new ArrayList<>();
        //从缓存中获取key
        String cartKey = this.getCartKey(userId);
        //获取登录购物车的数据  key, field, value(cartKey,skuId.toString,cartInfoExist)
        BoundHashOperations<String, String, CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);

        //  判断未登录购物车集合有数据！
        if (!CollectionUtils.isEmpty(noLoginCartInfoList)) {
            noLoginCartInfoList.stream().forEach(cartInfo -> {
                //  if (cartInfo.getSkuId().intValue()==info.getSkuId().intValue()){
                //  21,22,23
                if (boundHashOperations.hasKey(cartInfo.getSkuId().toString())) {
                    //  说明有相同的skuId！ hget key field;
                    CartInfo cartInfoLogin = boundHashOperations.get(cartInfo.getSkuId().toString());
                    //  修改数量
                    cartInfoLogin.setSkuNum(cartInfoLogin.getSkuNum() + cartInfo.getSkuNum());
                    //  修改时间
                    cartInfoLogin.setUpdateTime(new Date());
                    //  查询一下实时价格
                    cartInfoLogin.setSkuPrice(this.productFeignClient.getSkuPrice(cartInfo.getSkuId()));
                    //  选中..... 未登录状态为1 ，则修改登录选中状态！
                    if (cartInfo.getIsChecked().intValue() == 1) {
//                        if (cartInfoLogin.getIsChecked().intValue()==0){
//                            cartInfoLogin.setIsChecked(1);
//                        }
                        //  将数据库的选中状态赋值为1
                        cartInfoLogin.setIsChecked(1);
                    }
                    //  写入进去！
                    boundHashOperations.put(cartInfo.getSkuId().toString(), cartInfoLogin);
                } else {
                    //  不行！ 24
                    cartInfo.setUserId(userId);
                    cartInfo.setCreateTime(new Date());
                    cartInfo.setUpdateTime(new Date());
                    //  写入进去！
                    boundHashOperations.put(cartInfo.getSkuId().toString(), cartInfo);
                }
            });
            //  删除临时购物车数据：
            this.redisTemplate.delete(this.getCartKey(userTempId));
        }

        //  查询最终合并之后的数据结果集： hvals key;
        List<CartInfo> loginCartInfoList = redisTemplate.opsForHash().values(cartKey);
        //  判断 如果登录购物车为空返回空集合
        if (CollectionUtils.isEmpty(loginCartInfoList)) {
            //  默认返回空集合
            return new ArrayList<>();
        }

        //  排序：
        loginCartInfoList.sort((o1, o2) -> {
            //  返回比较结果！
            return o2.getUpdateTime().compareTo(o1.getUpdateTime());
        });
        //方法1.双重for循环
        //if (!StringUtils.isEmpty(userId)) {
        //    //从缓存中获取key
        //    String cartKey = this.getCartKey(userId);
        //    //hset key field hget key field  hgetAll key [key value]  hvals key [value]
        //    LoginCartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //
        //    //双重for循环 进行合并数据 未登录合并到登录的里面
        //    if (!CollectionUtils.isEmpty(noLoginCartInfoList)){
        //        for (CartInfo cartInfo : noLoginCartInfoList) {
        //            for (CartInfo info : LoginCartInfoList) {
        //                if (cartInfo.getSkuId().intValue()==info.getSkuId().intValue()){
        //                    //数量 相加，修改时间。。
        //
        //                }else{
        //                    // insert createTime updateTime
        //                }
        //            }
        //        }
        //        //删除未登录购物车数据
        //        this.redisTemplate.delete(this.getCartKey(userTempId));
        //    }
        //再次查询数据
        //排序
        return loginCartInfoList;
    }

    @Override
    public void checkCart(Long skuId, String userId, Integer isChecked) {
        //  修改数据！
        //  获取key
        String cartKey = this.getCartKey(userId);

        //  先根据key 来获取数据！ hget key field
        CartInfo cartInfo = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
        //  判断
        if (cartInfo != null) {
            cartInfo.setIsChecked(isChecked);
        }
        //  放入缓存！
        this.redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfo);

    }

    @Override
    public void deleteCart(Long skuId, String userId) {
        //  hdel key field
        //  获取购物车key
        String cartKey = this.getCartKey(userId);

        //  可以通过先判断key 是否存在，再决定是否删除！  与 直接删除 一样！
        //  Boolean aBoolean = this.redisTemplate.opsForHash().hasKey(cartKey, skuId.toString());
        //  this.redisTemplate.opsForHash().delete(cartKey,skuId.toString());

        //        BoundHashOperations boundHashOperations = this.redisTemplate.boundHashOps(cartKey);
        //        if (boundHashOperations.hasKey(skuId.toString())){
        //            //  删除数据！
        //            boundHashOperations.delete(skuId.toString());
        //        }
        //  删除数据！
        this.redisTemplate.boundHashOps(cartKey).delete(skuId.toString());

    }

    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        //获取选中商品的购物车列表  通过用户id获取缓存key
        String cartKey = this.getCartKey(userId);
        //获取到购物车的集合数据
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);

        //过滤购物车中未选中的商品 isChecked==0
        List<CartInfo> cartInfoCheckedList = cartInfoList.stream().filter(cartInfo -> {
            //重新确认购物车最新的价格
            cartInfo.setSkuPrice(this.productFeignClient.getSkuPrice(cartInfo.getSkuId()));
            return cartInfo.getIsChecked().intValue() == 1;
        }).collect(Collectors.toList());
        //返回数据
        return cartInfoCheckedList;
    }

    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }
}
